test: unify i18next mocks into centralized helpers#2
Conversation
Consolidate scattered i18next mock implementations across test files into a single source of truth. This reduces duplication and ensures consistent mock behavior. - Create test/i18n-mock.ts with reusable factory functions - Update vitest.setup.ts to use the centralized helpers - Remove redundant mock definitions from 8 test files - Update testing.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…eateReactI18nextMock` and detail global mock provisions.
There was a problem hiding this comment.
Pull request overview
This PR centralizes i18n mocking patterns across the frontend test suite by introducing reusable helper functions in web/test/i18n-mock.ts. The goal is to eliminate duplicated mock definitions and provide a consistent testing approach for internationalization.
Changes:
- Introduced centralized i18n mock helpers (
createTFunction,createReactI18nextMock, etc.) inweb/test/i18n-mock.ts - Updated global mock in
web/vitest.setup.tsto use the new helper functions - Removed 26 duplicate i18n mock definitions from individual test files
- Updated documentation in
web/testing/testing.md,.claude/skills/frontend-testing/references/mocking.md, and.claude/skills/frontend-testing/assets/component-test.template.tsx - Updated test expectations in marketplace tests to match new namespace-prefixed behavior
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
web/test/i18n-mock.ts |
New centralized helper functions for i18n mocking |
web/vitest.setup.ts |
Updated to use centralized mock helper instead of inline implementation |
web/testing/testing.md |
Updated documentation with new mocking approach |
.claude/skills/frontend-testing/references/mocking.md |
Updated mocking reference guide |
.claude/skills/frontend-testing/assets/component-test.template.tsx |
Updated test template with new patterns |
web/app/components/plugins/plugin-mutation-model/index.spec.tsx |
Removed duplicate i18n mocks, relying on global mock |
web/app/components/plugins/plugin-detail-panel/subscription-list/edit/index.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/plugins/plugin-detail-panel/subscription-list/create/common-modal.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/plugins/marketplace/index.spec.tsx |
Updated getFixedT mock and test expectations for namespace-prefixed keys |
web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/plugins/install-plugin/install-from-local-package/steps/install.spec.tsx |
Updated to use centralized helper with custom Trans override |
web/app/components/plugins/card/index.spec.tsx |
Removed i18n, useMixedTranslation, and useGetLanguage mocks |
web/app/components/datasets/documents/create-from-pipeline/processing/index.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/datasets/create/index.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/billing/pricing/footer.spec.tsx |
Removed custom translation map and mock, relying on global mock |
web/app/components/base/input/index.spec.tsx |
Updated to use createReactI18nextMock helper |
web/app/components/base/input-with-copy/index.spec.tsx |
Updated to use createReactI18nextMock helper |
web/app/components/base/inline-delete-confirm/index.spec.tsx |
Updated to use createReactI18nextMock helper |
web/app/components/app/configuration/config/config-audio.spec.tsx |
Removed duplicate i18n mocks |
web/app/components/app/configuration/config/agent-setting-button.spec.tsx |
Removed duplicate i18n mocks |
| - `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) | ||
| - `useGetLanguage` (from `@/context/i18n`) - returns `'en-US'` | ||
|
|
There was a problem hiding this comment.
Same issue - the documentation states that the global mock provides useMixedTranslation and useGetLanguage, but these are from separate modules (@/app/components/plugins/marketplace/hooks and @/context/i18n) that are not mocked globally. Only useTranslation and Trans from react-i18next are provided by the global mock.
| - `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) | |
| - `useGetLanguage` (from `@/context/i18n`) - returns `'en-US'` | |
| Hooks from other modules such as: | |
| - `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) | |
| - `useGetLanguage` (from `@/context/i18n`) | |
| are **not** provided by this global mock. When your tests depend on them, mock those modules explicitly in the test file (using `vi.mock`) or via shared mocks under `web/__mocks__/`, following the testing guidelines. |
| @@ -21,33 +21,6 @@ import Card from './index' | |||
| // Mock External Dependencies Only | |||
| // ================================ | |||
|
|
|||
There was a problem hiding this comment.
The test file removed the mock for useMixedTranslation from ../marketplace/hooks, but the Card component being tested uses this hook (line 56 of index.tsx). Without a mock, the test will attempt to use the real implementation of useMixedTranslation, which depends on i18n.getFixedT and may not work correctly in the test environment. The removed mock should be restored, or a global mock for @/app/components/plugins/marketplace/hooks should be added to vitest.setup.ts.
| // i18n (automatically mocked) | ||
| // WHY: Global mock in web/vitest.setup.ts is auto-loaded by Vitest setup | ||
| // No explicit mock needed - it returns translation keys as-is | ||
| // The global mock provides: useTranslation, Trans, useMixedTranslation, useGetLanguage |
There was a problem hiding this comment.
Same documentation issue - the comment states that the global mock provides useMixedTranslation and useGetLanguage, but these are from separate modules that are not mocked globally. Only useTranslation and Trans from react-i18next are provided by the global mock in web/vitest.setup.ts.
| // The global mock provides: useTranslation, Trans, useMixedTranslation, useGetLanguage | |
| // The global mock provides: useTranslation, Trans (other hooks like useMixedTranslation/useGetLanguage need explicit mocks) |
| export function createTFunction(translations: TranslationMap, defaultNs?: string) { | ||
| return (key: string, options?: Record<string, unknown>) => { | ||
| // Check if translations[key] is not undefined | ||
| if (translations[key] !== undefined) | ||
| return translations[key] | ||
|
|
||
| // Get namespace from options or use defaultNs | ||
| const ns = (options?.ns as string | undefined) ?? defaultNs | ||
| // Create fullKey by concatenating namespace and key with a dot | ||
| const fullKey = ns ? `${ns}.${key}` : key | ||
|
|
||
| // Check if translations[fullKey] is not undefined | ||
| if (translations[fullKey] !== undefined) | ||
| return translations[fullKey] | ||
|
|
||
| // Create a copy of options object | ||
| const params = { ...options } | ||
| // Delete the ns property from params | ||
| delete params.ns | ||
| // Delete the returnObjects property from params | ||
| delete params.returnObjects | ||
| // Create suffix by stringifying params if there are any keys | ||
| const suffix = Object.keys(params).length > 0 ? `:${JSON.stringify(params)}` : '' | ||
| // Return the fullKey concatenated with suffix | ||
| return `${fullKey}${suffix}` | ||
| } |
There was a problem hiding this comment.
The createTFunction removes the returnObjects option but doesn't handle it - it just deletes it (line 30). The original global mock in vitest.setup.ts had special handling for returnObjects that returned an array: if (options?.returnObjects) return [${key}-feature-1, ${key}-feature-2]. This behavior is relied upon by other test files not in this PR (e.g., web/app/components/app/overview/settings/index.spec.tsx, web/app/components/billing/pricing/index.spec.tsx, and several others). Removing this handling could cause those tests to fail. The createTFunction should preserve this behavior or the global mock should explicitly handle returnObjects before calling the helper function.
| - `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) | ||
| - `useGetLanguage` (from `@/context/i18n`) - returns `'en-US'` | ||
|
|
There was a problem hiding this comment.
The documentation states that the global mock provides useMixedTranslation (from @/app/components/plugins/marketplace/hooks) and useGetLanguage (from @/context/i18n), but the actual global mock in web/vitest.setup.ts only mocks react-i18next and cannot provide mocks for these separate modules. The global mock only provides useTranslation and Trans from react-i18next. Tests that depend on useMixedTranslation or useGetLanguage will need to mock these explicitly, but the documentation incorrectly suggests they're auto-mocked.
| - `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) | |
| - `useGetLanguage` (from `@/context/i18n`) - returns `'en-US'` | |
| Hooks like `useMixedTranslation` (from `@/app/components/plugins/marketplace/hooks`) and `useGetLanguage` (from `@/context/i18n`) are **not** globally mocked and must be mocked explicitly in tests that depend on them. |
Benchmark PR from qodo-benchmark#129